﻿using HandyControl.Controls;
using Ping9719.WpfEx;
using Ping9719.WpfEx.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace BaseUi.ViewModel
{
    public class DeviceViewModel : BindableBase
    {
        //循环间隙时间
        int whileSleep = 1500;
        /// <summary>
        /// 是否繁忙。繁忙状态下不在进行定时刷新操作。
        /// </summary>
        public bool IsBusy { get; set; } = false;
        //public IIoTBase plc;

        #region 属性
        /// <summary>
        /// 监听
        /// </summary>
        public IEnumerable<DeviceReadModel> DataReads { get; set; }
        /// <summary>
        /// 控制
        /// </summary>
        public IEnumerable<DeviceWriteModel> DataWrites { get; set; }
        /// <summary>
        /// 气缸
        /// </summary>
        public IEnumerable<DeviceUrnModel> DataUrns { get; set; }
        /// <summary>
        /// 伺服
        /// </summary>
        public IEnumerable<DeviceServoModel> DataServos { get; set; }

        private bool IsVis_ = false;
        /// <summary>
        /// 当前页面是否显示
        /// </summary>
        public bool IsVis { get => IsVis_; set { SetProperty(ref IsVis_, value); } }

        #region 是否展示
        private bool IsVisRead_ = true;
        public bool IsVisRead { get => IsVisRead_; set { SetProperty(ref IsVisRead_, value); } }

        private bool IsVisWrite_ = true;
        public bool IsVisWrite { get => IsVisWrite_; set { SetProperty(ref IsVisWrite_, value); } }

        private bool IsVisUrn_ = true;
        public bool IsVisUrn { get => IsVisUrn_; set { SetProperty(ref IsVisUrn_, value); } }

        private bool IsVisServo_ = true;
        public bool IsVisServo { get => IsVisServo_; set { SetProperty(ref IsVisServo_, value); } }
        #endregion

        #region 是否折叠
        private bool IsVisExpRead_ = true;
        public bool IsVisExpRead { get => IsVisExpRead_; set { SetProperty(ref IsVisExpRead_, value); } }

        private bool IsVisExpWrite_ = true;
        public bool IsVisExpWrite { get => IsVisExpWrite_; set { SetProperty(ref IsVisExpWrite_, value); } }

        private bool IsVisExpUrn_ = false;
        public bool IsVisExpUrn { get => IsVisExpUrn_; set { SetProperty(ref IsVisExpUrn_, value); } }

        private bool IsVisExpServo_ = false;
        public bool IsVisExpServo { get => IsVisExpServo_; set { SetProperty(ref IsVisExpServo_, value); } }
        #endregion

        #endregion

        /// <summary>
        /// 循环读取数据
        /// </summary>
        public async void WhileRead()
        {
            while (true)
            {
                try
                {
                    if (!IsVis || IsBusy)
                    {
                        await Task.Delay(whileSleep);
                        continue;
                    }

                    ////监控
                    if (DataReads != null && IsVisExpRead)
                    {
                        foreach (var item in DataReads)
                        {
                            if (!item.IsExpanded)
                                continue;

                            var plcAdd = item.ExcelTag;
                            if (string.IsNullOrWhiteSpace(plcAdd.地址))
                                continue;

                            var ts = plcAdd.类型.Trim().ToLower();
                            switch (ts)
                            {
                                case "bool":
                                    //var datab = plc?.Read<bool>(plcAdd.地址);
                                    //item.Value = datab?.IsSucceed == true ? datab.Value : false;
                                    break;
                                case "byte":
                                    //var datay = plc?.Read<byte>(plcAdd.地址);
                                    //item.Value = datay?.IsSucceed == true ? datay.Value : "-";
                                    break;
                                case "int16":
                                    //var datai16 = plc?.Read<Int16>(plcAdd.地址);
                                    //item.Value = datai16?.IsSucceed == true ? datai16.Value : "-";
                                    break;
                                case "int32":
                                    //var datai32 = plc?.Read<int>(plcAdd.地址);
                                    //item.Value = datai32?.IsSucceed == true ? datai32.Value : "-";
                                    break;
                                case "uint16":
                                    //var dataui16 = plc?.Read<UInt16>(plcAdd.地址);
                                    //item.Value = dataui16?.IsSucceed == true ? dataui16.Value : "-";
                                    break;
                                case "uint32":
                                    //var dataui32 = plc?.Read<UInt32>(plcAdd.地址);
                                    //item.Value = dataui32?.IsSucceed == true ? dataui32.Value : "-";
                                    break;
                                case "float":
                                case "single":
                                    //var datas = plc?.Read<float>(plcAdd.地址);
                                    //item.Value = datas?.IsSucceed == true ? datas.Value : "-";
                                    break;
                                case "double":
                                    //var datad = plc?.Read<double>(plcAdd.地址);
                                    //item.Value = datad?.IsSucceed == true ? datad.Value : "-";
                                    break;
                                default:
                                    break;
                            }
                        }
                    }

                    ////控制
                    if (DataWrites != null && IsVisExpWrite)
                    {
                        foreach (var item in DataWrites)
                        {
                            if (!item.IsExpanded)
                                continue;

                            var plcAdd = item.ExcelTag;
                            if (string.IsNullOrWhiteSpace(plcAdd.读地址))
                                continue;

                            var ts = plcAdd.类型.Trim().ToLower();
                            switch (ts)
                            {
                                case "bool":
                                    //var datab = plc?.Read<bool>(plcAdd.读地址);
                                    //item.Value = datab?.IsSucceed == true ? datab.Value : false;
                                    break;
                                case "byte":
                                    //var datay = plc?.Read<byte>(plcAdd.读地址);
                                    //item.Value = datay?.IsSucceed == true ? datay.Value : "-";
                                    break;
                                case "int16":
                                    //var datai16 = plc?.Read<Int16>(plcAdd.读地址);
                                    //item.Value = datai16?.IsSucceed == true ? datai16.Value : "-";
                                    break;
                                case "int32":
                                    //var datai32 = plc?.Read<int>(plcAdd.读地址);
                                    //item.Value = datai32?.IsSucceed == true ? datai32.Value : "-";
                                    break;
                                case "uint16":
                                    //var dataui16 = plc?.Read<UInt16>(plcAdd.读地址);
                                    //item.Value = dataui16?.IsSucceed == true ? dataui16.Value : "-";
                                    break;
                                case "uint32":
                                    //var dataui32 = plc?.Read<UInt32>(plcAdd.读地址);
                                    //item.Value = dataui32?.IsSucceed == true ? dataui32.Value : "-";
                                    break;
                                case "float":
                                case "single":
                                    //var datas = plc?.Read<float>(plcAdd.读地址);
                                    //item.Value = datas?.IsSucceed == true ? datas.Value : "-";
                                    break;
                                case "double":
                                    //var datad = plc?.Read<double>(plcAdd.读地址);
                                    //item.Value = datad?.IsSucceed == true ? datad.Value : "-";
                                    break;
                                default:
                                    break;
                            }
                        }
                    }

                    ////气缸
                    if (DataUrns != null && IsVisExpUrn)
                    {
                        foreach (var item in DataUrns)
                        {
                            if (!item.IsExpanded)
                                continue;

                            var plcAdd = item.ExcelTag;
                            if (!string.IsNullOrWhiteSpace(plcAdd.推到位地址))
                            {
                                //var data1 = plc?.Read<bool>(plcAdd.推到位地址);
                                //item.IsGoTo = data1?.IsSucceed == true ? data1.Value : false;
                            }
                            if (!string.IsNullOrWhiteSpace(plcAdd.回到位地址))
                            {
                                //var data2 = plc?.Read<bool>(plcAdd.回到位地址);
                                //item.IsRetTo = data2?.IsSucceed == true ? data2.Value : false;
                            }
                        }
                    }

                    ////伺服
                    if (DataServos != null && IsVisExpServo)
                    {
                        foreach (var item in DataServos)
                        {
                            if (!item.IsExpanded)
                                continue;

                            ////读取地址信息
                            var plcAdd = item.ExcelTag;
                            if (!string.IsNullOrWhiteSpace(plcAdd.当前位置获取))
                            {
                                //var data1 = plc?.Read<float>(plcAdd.当前位置获取);
                                //item.Location = data1?.IsSucceed == true ? data1.Value : 0;
                            }
                            if (!string.IsNullOrWhiteSpace(plcAdd.手动速度获取) && (item.IsJog || !item.IsFold))
                            {
                                //var data2 = plc?.Read<Int16>(plcAdd.手动速度获取);
                                //item.JogSpeed = data2?.IsSucceed == true ? data2.Value : 0;
                            }
                            if (!string.IsNullOrWhiteSpace(plcAdd.自动速度设置) && (!item.IsJog || !item.IsFold))
                            {
                                //var data3 = plc?.Read<Int16>(plcAdd.自动速度设置);
                                //item.AutoSpeed = data3?.IsSucceed == true ? data3.Value : 0;
                            }
                        }
                    }

                    await Task.Delay(whileSleep);
                }
                catch (Exception)
                {

                }
            }
        }

        /*一起选中【操作控制】【操作气缸】【操作伺服】可以快速解开全部注释*/

        #region 操作控制
        ////单击
        public void WriteClick(object sender, RoutedEventArgs e)
        {
            var data = (DeviceWriteModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (dataExcel.类型.Trim().ToLower() == "bool" && mode.StartsWith("切换"))
            {
                Task.Run(() =>
                {
                    var boolval = data.Value is true;
                    //plc?.Write(dataExcel.写地址, !boolval);
                    data.Value = !boolval;
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "控制", Funct = string.Empty, Val = data.Value, Mode = mode });
                });
            }
            else
            {
                var ts = dataExcel.类型.Trim().ToLower();
                switch (ts)
                {
                    case "byte":
                        WriteClickDialog<byte>(data);
                        break;
                    case "int16":
                        WriteClickDialog<Int16>(data);
                        break;
                    case "int32":
                        WriteClickDialog<Int32>(data);
                        break;
                    case "uint16":
                        WriteClickDialog<UInt16>(data);
                        break;
                    case "uint32":
                        WriteClickDialog<UInt32>(data);
                        break;
                    case "float":
                    case "single":
                        WriteClickDialog<float>(data);
                        break;
                    case "double":
                        WriteClickDialog<double>(data);
                        break;
                    default:
                        break;
                }
            }
        }

        ////单击弹框
        void WriteClickDialog<T>(DeviceWriteModel data) where T : struct
        {
            var dataExcel = data.ExcelTag;
            var val = TipInputView.Show<T>($"请输入新的[{dataExcel.名称}]值：", "修改值", "请输入值");
            if (!val.HasValue)
                return;

            //plc?.Write<T>(dataExcel.写地址, val.Value);
            IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "控制", Funct = string.Empty, Val = val.Value, Mode = "" });
        }

        ////按下左键
        public void LeftDown(object sender, MouseButtonEventArgs e)
        {
            var data = (DeviceWriteModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (dataExcel.类型.Trim().ToLower() == "bool" && mode.StartsWith("点动"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.写地址, true);
                    data.Value = true;
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "控制", Funct = string.Empty, Val = data.Value, Mode = mode });
                });
            }
        }

        ////放开左键
        public void LeftUp(object sender, MouseButtonEventArgs e)
        {
            var data = (DeviceWriteModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (dataExcel.类型.Trim().ToLower() == "bool" && mode.StartsWith("点动"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.写地址, false);
                    data.Value = false;
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "控制", Funct = string.Empty, Val = data.Value, Mode = mode });
                });
            }
        }
        #endregion

        #region 操作气缸
        ////按钮1单击
        public void Button1_Click(object sender, RoutedEventArgs e)
        {
            var data = (DeviceUrnModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (mode.StartsWith("切换"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.推地址, true);
                    //plc?.Write(dataExcel.回地址, false);
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "气缸", Funct = "推", Val = true, Mode = mode });
                });
            }
        }

        ////按钮1按下
        public void But1ClickDown(object sender, RoutedEventArgs e)
        {
            var data = (DeviceUrnModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (mode.StartsWith("点动"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.推地址, true);
                    data.IsGoTo = true;
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "气缸", Funct = "推", Val = true, Mode = mode });
                });
            }
        }

        ////按钮1松开
        public void But1ClickUp(object sender, RoutedEventArgs e)
        {
            var data = (DeviceUrnModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (mode.StartsWith("点动"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.推地址, false);
                    data.IsGoTo = false;
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "气缸", Funct = "推", Val = false, Mode = mode });
                });
            }
        }

        ////按钮2单击
        public void Button2_Click(object sender, RoutedEventArgs e)
        {
            var data = (DeviceUrnModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (mode.StartsWith("切换"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.推地址, false);
                    //plc?.Write(dataExcel.回地址, true);
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "气缸", Funct = "回", Val = true, Mode = mode });
                });
            }
        }

        ////按钮2按下
        public void But2ClickDown(object sender, RoutedEventArgs e)
        {
            var data = (DeviceUrnModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (mode.StartsWith("点动"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.回地址, true);
                    data.IsRetTo = true;
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "气缸", Funct = "回", Val = true, Mode = mode });
                });
            }
        }

        ////按钮2松开
        public void But2ClickUp(object sender, RoutedEventArgs e)
        {
            var data = (DeviceUrnModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = dataExcel.点动切换?.Trim() ?? "";

            if (mode.StartsWith("点动"))
            {
                Task.Run(() =>
                {
                    //plc?.Write(dataExcel.回地址, false);
                    data.IsRetTo = false;
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "气缸", Funct = "回", Val = false, Mode = mode });
                });
            }
        }
        #endregion

        #region 操作伺服
        ////尝试改变伺服的位置时
        public void LocationChange(object sender, RoutedEventArgs e)
        {
            var data = (DeviceServoModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = string.Empty;

            ////运动方式
            if (e.OriginalSource is ServoClickType servoClickType)
            {
                if (servoClickType == ServoClickType.StartDotAdd)
                {
                    //plc?.Write(dataExcel.位置点动加, true);
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "伺服", Funct = "开始点动加", Val = true, Mode = mode });
                }
                else if (servoClickType == ServoClickType.EndDotAdd)
                {
                    //plc?.Write(dataExcel.位置点动加, false);
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "伺服", Funct = "结束点动加", Val = false, Mode = mode });
                }
                else if (servoClickType == ServoClickType.StartDotSub)
                {
                    //plc?.Write(dataExcel.位置点动减, true);
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "伺服", Funct = "开始点动减", Val = true, Mode = mode });
                }
                else if (servoClickType == ServoClickType.EndDotSub)
                {
                    //plc?.Write(dataExcel.位置点动减, false);
                    IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "伺服", Funct = "结束点动减", Val = false, Mode = mode });
                }
            }
            ////运动到指定位置
            else if (e.OriginalSource is double val)
            {
                //plc?.Write(dataExcel.位置移动, Convert.ToSingle(val));
                data.Location = val;
                IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "伺服", Funct = "位置移动", Val = val, Mode = mode });
            }
        }

        ////尝试改变伺服的速度时
        public void SpeedChange(object sender, RoutedEventArgs e)
        {
            var data = (DeviceServoModel)((FrameworkElement)sender).DataContext;
            var dataExcel = data.ExcelTag;
            var mode = string.Empty;

            var data2 = (ServoSpeed)e.OriginalSource;
            if (data2.Name.StartsWith("手动"))
            {
                //plc?.Write(dataExcel.手动速度设置, Convert.ToSingle(data2.Speed));
                data.JogSpeed = data2.Speed;
                IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "伺服", Funct = "手动速度设置", Val = data2.Speed, Mode = mode });
            }
            else
            {
                //plc?.Write(dataExcel.自动速度设置, Convert.ToSingle(data2.Speed));
                data.AutoSpeed = data2.Speed;
                IotDevice.UserChange?.Invoke(new IotDevice() { Name = data.Name, Type = "伺服", Funct = "自动速度设置", Val = data2.Speed, Mode = mode });

            }
        }
        #endregion
    }

    public class DeviceReadModel : BindableBase
    {
        #region 属性
        private string Name_;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get => Name_; set { SetProperty(ref Name_, value); } }

        private object Value_;
        /// <summary>
        /// 值
        /// </summary>
        public object Value { get => Value_; set { SetProperty(ref Value_, value); } }

        /// <summary>
        /// 是否可见
        /// </summary>
        public bool IsExpanded { get; set; }

        /// <summary>
        /// Excel原始数据
        /// </summary>
        public ExcelDeviceReadModel ExcelTag { get; set; }
        #endregion
    }

    public class DeviceWriteModel : BindableBase
    {
        #region 属性
        private string Name_;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get => Name_; set { SetProperty(ref Name_, value); } }

        private object Value_;
        /// <summary>
        /// 是否合格
        /// </summary>
        public object Value { get => Value_; set { SetProperty(ref Value_, value); } }

        /// <summary>
        /// 是否可见
        /// </summary>
        public bool IsExpanded { get; set; }

        /// <summary>
        /// Excel原始数据
        /// </summary>
        public ExcelDeviceWriteModel ExcelTag { get; set; }
        #endregion
    }

    public class DeviceUrnModel : BindableBase
    {
        #region 属性
        private string Name_;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get => Name_; set { SetProperty(ref Name_, value); } }

        private bool IsGoTo_;
        /// <summary>
        /// 是否推到位
        /// </summary>
        public bool IsGoTo { get => IsGoTo_; set { SetProperty(ref IsGoTo_, value); } }

        private bool IsRetTo_;
        /// <summary>
        /// 是否回到位
        /// </summary>
        public bool IsRetTo { get => IsRetTo_; set { SetProperty(ref IsRetTo_, value); } }

        /// <summary>
        /// 是否可见
        /// </summary>
        public bool IsExpanded { get; set; }

        /// <summary>
        /// 自定义数据
        /// </summary>
        public ExcelDeviceUrnModel ExcelTag { get; set; }
        #endregion
    }

    public class DeviceServoModel : BindableBase
    {
        #region 属性
        private string Name_;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get => Name_; set { SetProperty(ref Name_, value); } }

        private double JogSpeed_;
        /// <summary>
        /// 手动模式速度
        /// </summary>
        public double JogSpeed { get => JogSpeed_; set { SetProperty(ref JogSpeed_, value); } }

        private double AutoSpeed_;
        /// <summary>
        /// 自动模式速度
        /// </summary>
        public double AutoSpeed { get => AutoSpeed_; set { SetProperty(ref AutoSpeed_, value); } }

        private double Location_;
        /// <summary>
        /// 伺服当前位置
        /// </summary>
        public double Location { get => Location_; set { SetProperty(ref Location_, value); } }

        private bool IsJog_ = true;
        /// <summary>
        /// 是否主页显示为手动模式
        /// </summary>
        public bool IsJog { get => IsJog_; set { SetProperty(ref IsJog_, value); } }

        private bool IsFold_ = true;
        /// <summary>
        /// 是否折叠
        /// </summary>
        public bool IsFold { get => IsFold_; set { SetProperty(ref IsFold_, value); } }

        /// <summary>
        /// 是否可见
        /// </summary>
        public bool IsExpanded { get; set; }

        private ExcelDeviceServoModel ExcelTag_;
        /// <summary>
        /// 自定义数据
        /// </summary>
        public ExcelDeviceServoModel ExcelTag { get => ExcelTag_; set { SetProperty(ref ExcelTag_, value); } }
        #endregion
    }
}
